// use crate::type_definition::CookieParams;
use crate::{EtaxR, RequestOption};
use common_uu::JsonV;
use std::ops::{Deref, DerefMut};
use std::path::Path;

/// 爬虫框架包装 trait
#[cfg(feature = "use_sync")]
pub trait DriverTrait<T: Sync + Send>
where
    Self: Sync + Send + Deref<Target = T> + DerefMut<Target = T>,
{
    fn new(data: T) -> EtaxR<Self>
    where
        Self: Sized;

    /// 刷新
    fn refresh(&self) -> EtaxR<()>;

    /// 导航
    fn navigate_to(&self, url: &str) -> EtaxR<()>;

    fn open_new_windows(&self, url: &str) -> EtaxR<()>;

    fn current_url(&self) -> EtaxR<String>;

    /// 点击
    fn click(&self, selector: &str) -> EtaxR<()>;

    /// 点击匹配到的内容
    fn click_by_content(&self, selector: &str, content: &str) -> EtaxR<()>;

    /// 移除元素
    fn remove(&self, selector: &str) -> EtaxR<()>;

    /// 点击 alert
    fn click_alert(&self) -> EtaxR<()>;

    /// 失去焦点
    fn blur(&self, selector: Option<String>) -> EtaxR<()>;

    /// 获得元素
    fn is_exist(&self, selector: &str) -> EtaxR<bool>;

    /// 获得元素
    fn get_values(&self, selectors: &str) -> EtaxR<Vec<String>>;

    /// 获得值
    fn get_value(&self, selector: &str) -> EtaxR<String>;

    /// 获得值-超时时间
    fn get_value_timeout(&self, selector: &str, time: u64) -> EtaxR<String>;

    /// 获得属性值
    fn get_attribute(&self, selector: &str, attribute_name: &str) -> EtaxR<JsonV>;

    /// 获得属性值
    fn get_attributes(&self, selector: &str, attribute_name: &str) -> EtaxR<Vec<String>>;

    /// 获得 style css属性
    fn get_css_property(&self, selector: &str, css_name: &str) -> EtaxR<JsonV>;

    /// 输入值
    fn input(&self, selector: &str, value: JsonV) -> EtaxR<JsonV>;

    /// 获得元素定位 (x, y, width, height)
    fn get_rec(&self, selector: &str) -> EtaxR<(i64, i64, i64, i64)>;

    /// 移动偏移量
    fn move_by_offset(&self, selector: &str, x: i32, y: i32) -> EtaxR<()>;

    /// 移动元素
    fn move_element(
        &self,
        selector: &str,
        position_from: (i64, i64),
        position_to: (i64, i64),
    ) -> EtaxR<()>;

    /// 执行JS
    fn exec_js(&self, js: &str) -> EtaxR<JsonV>;

    /// 执行JS
    fn exec_js_by_selector(&self, selector: &str, js: &str) -> EtaxR<JsonV>;

    /// 切换到tab
    fn swith_tab(&self, index: i64) -> EtaxR<()>;

    /// 切换到最后一个tab
    fn swith_tab_by_last(&self) -> EtaxR<()>;

    /// 切换到 iframe
    fn swith_iframe(&self, index: i64) -> EtaxR<()>;

    /// 关闭tab
    fn close_tab(&self) -> EtaxR<()>;

    /// 截图
    fn capture_screenshot(&self, selector: &str, path: &Path) -> EtaxR<()>;

    fn add_cookie(&self, cookie: super::Cookie) -> EtaxR<()>;

    /// 获得cookies
    fn get_cookies(&self) -> EtaxR<Vec<super::Cookie>>;

    /// 获得cookies字符串
    fn get_cookies2(&self) -> EtaxR<Option<String>>;

    /*fn get_with_cookie(&self, params: &dyn CookieParams) -> EtaxR<JsonV>;

    fn post_with_cookie(&self, params: &dyn CookieParams, body: JsonV) -> EtaxR<JsonV>;*/
}

#[async_trait::async_trait]
pub trait DriverTrait<T: Sync + Send>
where
    Self: Sync + Send + Deref<Target = T> + DerefMut<Target = T>,
{
    async fn new(data: T) -> EtaxR<Self>
    where
        Self: Sized;

    /// 刷新
    async fn refresh(&self) -> EtaxR<()>;

    /// 导航
    async fn navigate_to(&self, url: &str) -> EtaxR<()>;

    async fn open_new_windows(&self, url: &str) -> EtaxR<()>;

    async fn current_url(&self) -> EtaxR<String>;

    async fn send_keys(&self, selector: &str, keys: thirtyfour::TypingData) -> EtaxR<()>;

    /// 点击
    async fn click(&self, selector: &str) -> EtaxR<()>;

    /// 点击
    async fn click_retry(&self, selector: &str, count: u64) -> EtaxR<()>;

    /// 点击匹配到的内容
    async fn click_by_content(&self, selector: &str, content: &str) -> EtaxR<()>;

    /// 移除元素
    async fn remove(&self, selector: &str) -> EtaxR<()>;

    /// 点击 alert
    async fn click_alert(&self) -> EtaxR<()>;

    /// 失去焦点
    async fn blur(&self, selector: Option<String>) -> EtaxR<()>;

    /// 获得元素
    async fn is_exist(&self, selector: &str) -> EtaxR<bool>;

    /// 获得元素
    async fn get_values(&self, selectors: &str) -> EtaxR<Vec<String>>;

    /// 获得值
    async fn get_value(&self, selector: &str) -> EtaxR<String>;

    async fn get_value_retry(&self, selector: &str, count: u64) -> EtaxR<String>;

    /// 获得属性值
    async fn get_attribute(&self, selector: &str, attribute_name: &str) -> EtaxR<JsonV>;

    /// 获得属性值
    async fn get_attributes(&self, selector: &str, attribute_name: &str) -> EtaxR<Vec<String>>;

    /// 获得 style css属性
    async fn get_css_property(&self, selector: &str, css_name: &str) -> EtaxR<JsonV>;

    /// 输入值
    async fn input(&self, selector: &str, value: JsonV) -> EtaxR<JsonV>;

    /// 获得元素定位 (x, y, width, height)
    async fn get_rec(&self, selector: &str) -> EtaxR<(i64, i64, i64, i64)>;

    /// 移动偏移量
    async fn move_by_offset(&self, selector: &str, x: i32, y: i32) -> EtaxR<()>;

    /// 移动元素
    async fn move_element(
        &self,
        selector: &str,
        position_from: (i64, i64),
        position_to: (i64, i64),
    ) -> EtaxR<()>;

    /// 执行JS
    async fn exec_js(&self, js: &str) -> EtaxR<JsonV>;

    /// 执行JS
    async fn request_option(&self, url: String, op: RequestOption) -> EtaxR<JsonV>;

    /// 执行JS
    async fn request(
        &self,
        url: String,
        method: crate::ReqMethod,
        data: JsonV,
        content_type: Option<crate::ReqContentType>,
        data_type: Option<crate::ResType>,
    ) -> EtaxR<JsonV>;

    /// 执行JS
    async fn exec_js_by_selector(&self, selector: &str, js: &str) -> EtaxR<JsonV>;

    /// 切换到tab
    async fn swith_tab(&self, index: i64) -> EtaxR<()>;

    /// 切换到最后一个tab
    async fn swith_tab_by_last(&self) -> EtaxR<()>;

    /// 切换到 iframe
    async fn swith_iframe(&self, index: i64) -> EtaxR<()>;

    /// 关闭tab
    async fn close_tab(&self) -> EtaxR<()>;

    /// 关闭tab
    async fn close_tab_with_all(&self) -> EtaxR<()>;

    async fn screenshot_as_base64(&self, selector: &str) -> EtaxR<String>;

    /// 截图
    async fn capture_screenshot(&self, selector: &str, path: &Path) -> EtaxR<()>;

    async fn add_cookie(&self, cookie: super::Cookie) -> EtaxR<()>;

    /// 获得cookies
    async fn get_cookies(&self) -> EtaxR<Vec<super::Cookie>>;

    /// 获得cookies字符串
    async fn get_cookies2(&self) -> EtaxR<Option<String>>;

    /*async fn get_with_cookie<P: CookieParams + Send>(&self, params: P) -> EtaxR<JsonV>;

    async fn post_with_cookie<P: CookieParams + Send>(
        &self,
        params: P,
        body: JsonV,
    ) -> EtaxR<JsonV>;*/
}
